﻿Public Class KundeProjektTaskFormAdapter(Of F As Form, L As KundeProjektTaskListener)
    Inherits FormAdapter(Of F, L)
    Implements KundeProjektTaskModelListener

    Private WithEvents cbxKunde As ComboBox = Nothing
    Private WithEvents cbxProjekt As ComboBox = Nothing
    Private WithEvents cbxTask As ComboBox = Nothing

    Private kunden As List(Of Kunde)
    Private selectedKunde As Kunde
    Private projekte As List(Of Projekt)
    Private selectedProjekt As Projekt
    Private tasks As List(Of Task)
    Private selectedTask As Task

    ' when ture, no one is notified when an event is handled
    Private blockEvents As Boolean = False

    Sub New(ByRef form As F)
        MyBase.New(form)
    End Sub

    Public Sub setComboboxes(ByRef cbxKunde As ComboBox, ByRef cbxProjekt As ComboBox, ByRef cbxTask As ComboBox)
        Me.cbxKunde = cbxKunde
        Me.cbxProjekt = cbxProjekt
        Me.cbxTask = cbxTask
    End Sub

    Public Overridable Sub onKundenChanged(ByRef kunden As System.Collections.Generic.List(Of Kunde)) Implements KundeProjektTaskModelListener.onKundenChanged
        Me.kunden = kunden
        Me.blockEvents = True
        If Not cbxKunde Is Nothing Then
            cbxKunde.SuspendLayout()

            ' Welches ist der Aktuelle Kunde ?
            Dim selectedIndex As Integer = -1
            cbxKunde.Items.Clear()
            For i As Integer = 0 To kunden.Count - 1 Step 1
                If kunden(i).Equals(Me.selectedKunde) Then
                    selectedIndex = i
                End If
                cbxKunde.Items.Add(kunden(i).firmenname)
            Next

            cbxKunde.SelectedIndex = selectedIndex

            ' wenn name von selected ändert --> text ändern
            Dim newKunde As New Kunde()
            If selectedIndex > -1 Then
                newKunde = kunden(selectedIndex)
            End If
            onSelectedKundeChanged(newKunde)

            'cbxProjekte ausgrauen wenn kein kunde ausgewählt:
            checkCbxProjekt()

            cbxKunde.ResumeLayout()
        End If
        Me.blockEvents = False
    End Sub

    ' wird ausgeführt, wenn a) ein Anderer Kunde ausgewählt wird oder b) wenn der Kunde selbst ändert.
    Public Overridable Sub onSelectedKundeChanged(ByRef kunde As Kunde) Implements KundeProjektTaskModelListener.onSelectedKundeChanged
        Me.blockEvents = True
        Me.projekte = kunde.projekte
        Me.selectedKunde = kunde
        If Not cbxKunde Is Nothing Then
            cbxKunde.Text = kunde.firmenname
        End If
        If Not cbxProjekt Is Nothing Then
            cbxProjekt.SuspendLayout()

            ' Welches ist das Aktuelle Projekt ?
            Dim selectedIndex As Integer = -1
            cbxProjekt.Items.Clear()
            For i As Integer = 0 To projekte.Count - 1 Step 1
                If projekte(i).Equals(Me.selectedProjekt) Then
                    selectedIndex = i
                End If
                ' dabei kann gleich die Combobox gefüllt werden...
                cbxProjekt.Items.Add(projekte(i).name)
            Next

            cbxProjekt.SelectedIndex = selectedIndex

            ' wenn name von selected ändert --> text ändern
            Dim newProjekt As New Projekt()
            If selectedIndex > -1 Then
                newProjekt = projekte(selectedIndex)
            End If
            onSelectedProjektChanged(newProjekt)



            ' aktivieren, da kunde ausgewählt wurde
            cbxProjekt.Enabled = True

            ' cbxTask ausgrauen checken:
            checkCbxTask()

            cbxProjekt.ResumeLayout()
        End If
        Me.blockEvents = False
    End Sub

    ' wird ausgeführt, wenn a) ein anderes Projekt ausgewählt wird oder b) wenn das Projekt selbst ändert.
    Public Overridable Sub onSelectedProjektChanged(ByRef projekt As Projekt) Implements KundeProjektTaskModelListener.onSelectedProjektChanged
        Me.blockEvents = True
        Me.tasks = projekt.tasks
        Me.selectedProjekt = projekt
        If Not cbxProjekt Is Nothing Then
            cbxProjekt.Text = projekt.name
        End If
        If Not cbxTask Is Nothing Then
            cbxTask.SuspendLayout()

            ' Welches ist der Aktuelle Task ?
            Dim selectedIndex As Integer = -1
            cbxTask.Items.Clear()
            For i As Integer = 0 To tasks.Count - 1 Step 1
                If tasks(i).Equals(Me.selectedTask) Then
                    selectedIndex = i
                End If
                ' dabei kann gleich die Combobox gefüllt werden...
                cbxTask.Items.Add(tasks(i).titel)
            Next

            cbxTask.SelectedIndex = selectedIndex

            ' wenn name von selected ändert --> text ändern
            Dim newTask As New Task()
            If selectedIndex > -1 Then
                newTask = tasks(selectedIndex)
            End If
            onSelectedTaskChanged(newTask)

            ' eingrauen, es wurde ja ein projekt ausgewählt
            cbxTask.Enabled = True

            cbxTask.ResumeLayout()
        End If
        Me.blockEvents = False
    End Sub

    Public Overridable Sub onSelectedTaskChanged(ByRef task As Task) Implements KundeProjektTaskModelListener.onSelectedTaskChanged
        Me.selectedTask = task
        If Me.cbxTask IsNot Nothing Then
            Me.cbxTask.Text = task.titel
        End If
    End Sub

    Private Sub checkCbxProjekt()
        If Me.cbxProjekt IsNot Nothing Then
            Me.cbxProjekt.Enabled = cbxKunde.SelectedIndex <> -1
        End If
        checkCbxTask()
    End Sub

    Private Sub checkCbxTask()
        If Me.cbxTask IsNot Nothing Then
            Me.cbxTask.Enabled = cbxProjekt.SelectedIndex <> -1
        End If
    End Sub

    ' get Data:
    Public Function getKunde(ByVal index As Integer) As Kunde
        Return Me.kunden(index)
    End Function

    Public Function getProjekt(ByVal index As Integer) As Projekt
        Return Me.projekte(index)
    End Function

    Public Function getTask(ByVal index As Integer) As Task
        Return Me.tasks(index)
    End Function

    Public Function getSelectedKunde() As Kunde
        Return getNothingWhenIdNull(selectedKunde)
    End Function

    Public Function getSelectedProjekt() As Projekt
        Return getNothingWhenIdNull(selectedProjekt)
    End Function

    Public Function getSelectedTask() As Task
        Return getNothingWhenIdNull(selectedTask)
    End Function

    Private Function getNothingWhenIdNull(Of T As Base)(ByRef entity As T) As T
        If entity Is Nothing Then
            Return Nothing
        End If
        If entity.id = 0 Then
            Return Nothing
        End If
        Return entity
    End Function

    Public Function areRequiredComboboxesFilled() As Boolean
        If Me.cbxKunde IsNot Nothing Then
            If Me.getSelectedKunde Is Nothing Then
                Return False
            End If
        End If
        If Me.cbxProjekt IsNot Nothing Then
            If Me.getSelectedProjekt() Is Nothing Then
                Return False
            End If
        End If
        If Me.cbxTask IsNot Nothing Then
            If Me.getSelectedTask() Is Nothing Then
                Return False
            End If
        End If
        Return True
    End Function

    ' form events
    Public Sub on_kunde_change() Handles cbxKunde.SelectedIndexChanged
        If Not blockEvents Then
            Dim kunde As Kunde = Me.getKunde(cbxKunde.SelectedIndex)
            For Each listener As KundeProjektTaskListener In Me.getObservable().getListeners
                listener.onKundeChanged(kunde)
            Next
        End If
        onComboboxChange()
    End Sub

    Public Sub on_projekt_change() Handles cbxProjekt.SelectedIndexChanged
        If Not blockEvents Then
            Dim projekt As Projekt = Me.getProjekt(cbxProjekt.SelectedIndex)
            For Each listener As KundeProjektTaskListener In getObservable().getListeners
                listener.onProjektChanged(projekt)
            Next
        End If
        onComboboxChange()
    End Sub

    Public Sub on_task_change() Handles cbxTask.SelectedIndexChanged
        If Not blockEvents Then
            Dim task As Task = Me.getTask(cbxTask.SelectedIndex)
            For Each listener As KundeProjektTaskListener In getObservable().getListeners
                listener.onTaskChanged(task)
            Next
        End If
        onComboboxChange()
    End Sub

    Protected Overridable Sub onComboboxChange()
        ' here you can handle your checkbox changes easy in subclasses...
    End Sub
End Class
